
//
// XamlDesignView.cs
//
// Author:
//   Olivier Dufour
//
// Copyright (C) 2009 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.ComponentModel;

using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Commands;
//using MonoDevelop.Components.Commands;
using MonoDevelop.Core.Gui;
using MonoDevelop.Core.Execution;
using MonoDevelop.Projects;
using MonoDevelop.Projects.Text;
using MonoDevelop.Projects.Dom;
using MonoDevelop.DesignerSupport.Toolbox; 
//using MonoDevelop.DesignerSupport;
//using MonoDevelop.Deployment;
using Moonlight.Gtk;

using Gtk;
using Gdk;

using MonoDevelop.XamlDesigner;
using MonoDevelop.XamlDesigner.Controller;
using MonoDevelop.XamlDesigner.Model;
using MonoDevelop.XamlDesigner.Serialization;

using System.Xml;
using MonoDevelop.Components.Commands;
using MonoDevelop.DesignerSupport;
using System.Collections.Generic;
using System.Windows.Controls;

namespace MonoDevelop.XamlDesigner.View
{
	public class XamlDesignView : AbstractAttachableViewContent, ICustomFilteringToolboxConsumer//, IZoomable, IUndoHandler, IClipboardHandler
	{
        IViewContent viewContent;
		
		DesignerFrame designerFrame;
		
		bool activated = false;
		bool suppressSerialisation = false;
		static string extensionError = null;
        
		public XamlDesignView (IViewContent content)
		{
			this.viewContent = content;
            
            designerFrame = new DesignerFrame (this);
			designerFrame.CanFocus = true;
			designerFrame.Shadow = ShadowType.None;
			designerFrame.BorderWidth = 0;
			
			viewContent.WorkbenchWindow.Closing += workbenchWindowClosingHandler;
			viewContent.DirtyChanged += vcDirtyChanged;
			viewContent.BeforeSave += vcBeforeSave;
			
			designerFrame.Show ();
		}//TODO extend command cut/copy/paste,
        
		void workbenchWindowClosingHandler (object sender, WorkbenchWindowEventArgs args)
		{
			if (activated)
				suppressSerialisation = true;
		}
		
		void vcDirtyChanged (object sender, System.EventArgs e)
		{
			if (activated && !viewContent.IsDirty)
				viewContent.IsDirty = true;
		}
				
		void vcBeforeSave (object sender, System.EventArgs e)
		{
			if (activated)
				saveDocumentToTextView ();
		}

		public override Gtk.Widget Control {
			get { return designerFrame; }
		}
        public override string TabPageLabel {
			get { return "Designer"; }
		}
		
		bool disposed = false;
		
		public override void Dispose ()
		{
			if (disposed)
				return;
			
			disposed = true;
			
			base.WorkbenchWindow.Closing -= workbenchWindowClosingHandler;
			viewContent.DirtyChanged -= vcDirtyChanged;
			viewContent.BeforeSave -= vcBeforeSave;
			
			DesignerWidget.Dispose ();	
			designerFrame.Destroy ();
			base.Dispose ();
		}
        
		private MoonlightController controller;

		public MoonlightController Controller
		{
			get { return controller; }
			set { controller = value; }
		}
		//TODO add 4 buttons:BringForwards, BringToFront, SendBackwars, SendToBack

		MoonlightWidget DesignerWidget;
        
#region IToolboxConsumer implementation
        
		public void ConsumeItem (ItemToolboxNode node)
		{
		}
		
		public void DragItem (ItemToolboxNode item, Widget source, DragContext ctx)
		{
            controller.BeginDrag (item, source ,ctx);
		}
		
		public bool CustomFilterSupports (ItemToolboxNode item)
		{
		    return false;
		}
		
		public TargetEntry[] DragTargets {
		    get {//custom system
			return null;//new Gtk.TargetEntry[] { new Gtk.TargetEntry("application/x-?????", TargetFlags.App, 0)};
		    }
		}
		
		
		//used to filter toolbox items
		private static ToolboxItemFilterAttribute[] atts = new ToolboxItemFilterAttribute[] {
			//new ToolboxItemFilterAttribute ("Xaml Designer Tool", ToolboxItemFilterType.Require)
		};
			
		public ToolboxItemFilterAttribute[] ToolboxFilterAttributes {
			get { return atts; }
		}
		
		
		public string DefaultItemDomain {
		    get {
		        return GettextCatalog.GetString ("Moonlight Components");
		    }
		}
		
#endregion
        
		public override void Selected ()
		{
			DesignerWidget = new MoonlightWidget ();
            controller = new MoonlightController(DesignerWidget.Silver, this);
            
            VBox vbox = new VBox(false, 2);
            
            Toolbar toolbar = new Toolbar ();
			toolbar.IconSize = IconSize.Menu;
			toolbar.ToolbarStyle = ToolbarStyle.BothHoriz;
			toolbar.ShowArrow = false;
            
            selectionElementCombo = new WidgetTreeCombo (controller);
            toolbar.Add(selectionElementCombo);
            toolbar.ShowAll ();
                                    
            vbox.PackStart(toolbar, false, true, 1);
            vbox.PackEnd(DesignerWidget);
                            
			designerFrame.Add (vbox);
			designerFrame.ShowAll ();
			
			activated = true;

            MonoDevelop.DesignerSupport.DesignerSupport.Service.ToolboxService.ToolboxSelectionChanged += OnToolBoxSelectionChanged;
			
		}
        
        internal WidgetTreeCombo selectionElementCombo;
        
		public override void Deselected ()
		{
			LoggingService.LogError("Deselected");
			activated = false;
			
            MonoDevelop.DesignerSupport.DesignerSupport.Service.ToolboxService.ToolboxSelectionChanged -= OnToolBoxSelectionChanged;
            
			//don't need to save if window is closing
			if (!suppressSerialisation)
				saveDocumentToTextView ();
            
            designerFrame.Remove(DesignerWidget);
            DesignerWidget.Dispose ();
            designerFrame.Dispose ();
        }

        //set the current tool for xaml
		void OnToolBoxSelectionChanged (object sender, ToolboxSelectionChangedEventArgs e)
		{
            TypeToolboxNode tool = e.Item as TypeToolboxNode;
		    if (tool != null) {
                Type toolType = tool.Type.Load ();
                if (typeof(ITool).IsAssignableFrom (toolType)) {
	                object obj = System.Activator.CreateInstance(toolType, new object[] { controller });
					controller.CurrentTool = (ITool)obj;
                }
            }
		}

		public string GetSource ()
		{
		    ITextBuffer textBuf = (ITextBuffer) viewContent.GetContent (typeof(ITextBuffer));
		   	return textBuf.Text;
		}
        
		void saveDocumentToTextView ()
		{
			LoggingService.LogError("saveDocumentToTextView");
			IEditableTextBuffer textBuf = (IEditableTextBuffer) viewContent.GetContent (typeof(IEditableTextBuffer));
			textBuf.Text = controller.SerializeCanvas();
		}

		private static ToolboxItemFilterAttribute att = new ToolboxItemFilterAttribute ("Xaml Designer Tool", ToolboxItemFilterType.Require);
		
        #region ICustomFilteringToolboxConsumer implementation
        public bool SupportsItem (ItemToolboxNode item)
        {
            if (!item.ItemFilters.Contains(att))
                return false;
            //check if needed because ever done in dynamic ToolBoxprovider!
            if (controller.DrawingMode)
                return (item.Category == "Draw");
            else
                return (item.Category != "Draw");

        }
        #endregion

		class DesignerFrame: Frame
		{
			XamlDesignView view;
			
			public DesignerFrame (XamlDesignView view)
			{
				this.view = view;
			}
		}
        
	}
}
